from django.http import HttpResponse,JsonResponse
from django.shortcuts import render
from django.views import View
from libs.captcha.captcha import captcha
import django_redis
import random
from meiduo_mall.settings.dev import logger
from utils.response_code import RETCODE
import redis

# 实现短信验证码的显示
class SyscodeView(View):
    def get(self,request,mobile):
        """
        1.判断图形验证码是否一致,是否过期,不一致不能执行下一步
        1.1.删除对比后的图形验证码
        2.编写短信内容,通过三方平台发送
        2.1.生成短信内容--->6位随机
        2.2.保存短信内容,为校验作准备.
        2.2.返回给前端
        3.前端响应结果
        """
        image_code = request.GET.get('image_code')
        uuid = request.GET.get('image_code_id')
        # 为了测试暂时注销验证码校验功能
        try:
            redis_ob_col = django_redis.get_redis_connection("verify_image_code")
            redis_ob = redis_ob_col.get(uuid)
            if not redis_ob.decode():
                return JsonResponse({
                    "code":RETCODE.IMAGECODEERR,
                    "errmesg":"IMAGECODEERR"
                })
            # 这里注意下,通过redis数据库得到的是二进制的字符串,需要解码.
            # 这里做了一个不区分大小写的优化
            if redis_ob.decode().lower() != image_code.lower():
                return JsonResponse({
                    "code":RETCODE.THROTTLINGERR,
                    "errmesg":"THROTTLINGERR"
                })
            redis_ob_col.delete(uuid)
        except Exception as f:
            logger.error(f)
        # 生成验证码
        sys_verification = random.randint(100000,999999)
        # 存储到数据库,和数据库有关最好try一下
        sys_redis_ob = django_redis.get_redis_connection("sys_code")
        """优化功能通过上面链接redis数据库的对象.pipeline（）创建一个管道对象
        通过这个管道对象实现一次请求执行多个需求的方法，提高cpu效率。
        最后用管道对象.execute执行这个管道，类似mysql的事务，惰性方法"""
        p1 = sys_redis_ob.pipeline()
        """优化功能，防止爬虫直接跳过前端直接向服务器发送请求这里
        实现一个功能，给短信验证码的过期时间调成一分钟，然后作一个判断，
        当访问redis服务器使这个mobile的key还存在的时候我们不会再次发送短信"""
        if sys_redis_ob.get(mobile) :
            # 给前端响应结果
            return JsonResponse({
                "code":RETCODE.THROTTLINGERR,
                "errmseg":"请勿重复发送"
            })
        p1.setex(mobile,60,sys_verification)
        p1.execute()
        # 通过celery发送异步请求
        from celery_tasks.sms.tasks import Send_Ccp
        Send_Ccp.delay(mobile,sys_verification)

        return JsonResponse({
            "code":RETCODE.OK,
            "errmseg":"OK"
        })
# 实现图形验证码的显示
class ImagecodeView(View) :
    def get(self,request,uuid):

        """
        1.校验uuid(正则获取的无需校验)
        2.生成图形验证码:
        调用Captch类的generate的captcha方法生成两个验证码,text是我们存储到服务器的,
        image_code是给前端展示的
        3.链接redis数据库保存text--->django-redis
        4.返回给前端
        """
        text,image_code = captcha.generate_captcha()
        redis_ob = django_redis.get_redis_connection("verify_image_code")
        redis_ob.setex(uuid,120,text)
        return HttpResponse(image_code,content_type="image/jpg")


"""
短信验证码的实现：为了防止恶意发送短信，必须校验图形验证码，所以要检查
图形验证码的值和存在与否。
1 从前端提交的form表单提取出uuid和验证码的值（验证码在页面一刷新的时候前端就已经发送了
请求图形验证码。）
2 链接redis数据库，uuid是key，通过uuid取出对应的验证码的值（超时就没了）
2.1 从redis取出的值是bytes的，而且我们需要做一个不区分大小写的优化（比较式两端各加lower）
3.验证码校验通过后发送短信
3.1 生成短信内容（一个6位的数字）
3.2 保存到redis数据库中，key就是作为参数传入的mobile
3.2.1 优化方法一，通过redis缓存服务器的特性作为一个定时器，当这条缓存还存在是不能多次发送
短信验证码
3.2.2 优化方法二，因为代码从上往下执行如果同时执行多个redis语句操作当第一个操作未完成
其他的语句不能操作（及一次请求处理一个需求）。
所以通过redis的pipeline实现一个请求处理多个需求（打个包）.
3.3 通过三方包发送短信（这里用的是融链云）
3.3.1 优化方法 通过celery实现异步请求（跟上方pipeline的思想一样，无需等待上一条代码执行结束）
3.4 包的使用ccp.send_template(手机号,内容,超时时间,1)
4. 返回给前端
"""
"""
都需要设置api接口
图形验证码的实现：
1. 链接redis数据库
2. 通过第三方包captcha画图
2.1. 包的使用captcha.generate_captcha()
2.2. 使用两个变量接受这个值，其中text是我们存储到数据库的二进制的值，而image_code是
图片.
2.3. 返回给前端即可
"""